Thư viện dùng chung Thư_viện_(máy_tính)

Thư viện dùng chung hoặc đối tượng dùng chung là một file được dự định chia sẻ bởi các file thực thi và các file đối tượng được chia sẻ thêm. Các mô-đun được sử dụng bởi một chương trình được tải từ các đối tượng chia sẻ riêng lẻ vào bộ nhớ khi tải hoặc thời gian chạy, thay vì được sao chép bởi một trình liên kết khi nó tạo một file thực thi nguyên khối duy nhất cho chương trình.

Thư viện dùng chung có thể được liên kết tĩnh, nghĩa là các tham chiếu đến các mô-đun thư viện được giải quyết và các mô-đun được cấp phát bộ nhớ khi file thực thi được tạo. Nhưng thường liên kết các thư viện chia sẻ bị hoãn cho đến khi chúng được tải. [Còn mơ hồthảo luận]

Hầu hết các hệ điều hành hiện đại [NB 2] có thể có các file thư viện dùng chung định dạng với các file thực thi. Điều này cung cấp hai ưu điểm chính: thứ nhất, nó yêu cầu chỉ tạo một bộ tải cho cả hai, chứ không phải hai (có bộ tải đơn được coi là có giá trị phức tạp thêm vào). Thứ hai, nó cho phép các file thực thi cũng được sử dụng làm thư viện dùng chung, nếu chúng có bảng ký hiệu. Các định dạng thư viện chia sẻ và thực thi kết hợp điển hình là ELF và Mach-O (cả trong Unix) và PE (Windows).

Trong một số môi trường cũ hơn như Windows 16 bit hoặc MPE cho HP 3000, dữ liệu chỉ dựa trên ngăn xếp (cục bộ) được cho phép trong mã thư viện dùng chung hoặc các hạn chế đáng kể khác được đặt trên mã thư viện dùng chung.

Chia sẻ bộ nhớ

Mã thư viện có thể được chia sẻ trong bộ nhớ bởi nhiều tiến trình, cũng như trên đĩa. Nếu bộ nhớ ảo được sử dụng, các quy trình sẽ thực thi cùng một trang RAM vật lý được ánh xạ vào các không gian địa chỉ khác nhau của các quy trình. Điều này có lợi thế. Chẳng hạn, trên hệ thống OpenStep, các ứng dụng thường chỉ có kích thước vài trăm kilobyte và được tải nhanh chóng; phần lớn mã của họ được đặt trong các thư viện đã được hệ điều hành tải cho các mục đích khác.[cần dẫn nguồn]

Các chương trình có thể thực hiện chia sẻ RAM bằng cách sử dụng mã độc lập với vị trí, như trong Unix, dẫn đến kiến trúc phức tạp nhưng linh hoạt hoặc bằng cách sử dụng các địa chỉ ảo phổ biến, như trong Windows và OS/2. Các hệ thống này đảm bảo, bằng nhiều thủ thuật khác nhau như ánh xạ trước không gian địa chỉ và vị trí đặt chỗ cho mỗi thư viện dùng chung, mã đó có xác suất lớn được chia sẻ. Một lựa chọn thay thế thứ ba là bộ nhớ một cấp, được sử dụng bởi Hệ thống IBM/38 và những người kế nhiệm của nó. Điều này cho phép mã phụ thuộc vào vị trí, nhưng không đặt giới hạn đáng kể về nơi có thể đặt mã hoặc cách chia sẻ mã.

Trong một số trường hợp, các phiên bản khác nhau của thư viện dùng chung có thể gây ra sự cố, đặc biệt là khi các thư viện của các phiên bản khác nhau có cùng tên file và các ứng dụng khác nhau được cài đặt trên một hệ thống, mỗi ứng dụng yêu cầu một phiên bản cụ thể. Một kịch bản như vậy được gọi là địa ngục DLL, đặt theo tên file DLL của Windows và OS/2. Hầu hết các hệ điều hành hiện đại sau năm 2001 đều có các phương pháp dọn dẹp để loại bỏ các tình huống đó hoặc sử dụng các thư viện "riêng tư" dành riêng cho ứng dụng.[9]

Liên kết động

Liên kết động hoặc liên kết trễ là liên kết được thực hiện trong khi chương trình đang được tải (loadtime) hoặc được thực thi (runtime), thay vì khi file thực thi được tạo. Thư viện được liên kết động (thư viện liên kết động hay DLL, trong WindowsOS/2; đối tượng chia sẻ động hay DSO, trong các hệ thống giống Unix) là thư viện dành cho liên kết động. Chỉ một lượng công việc tối thiểu được thực hiện bởi trình liên kết khi file thực thi được tạo; nó chỉ ghi lại những gì thư viện thường xuyên chương trình cần và tên chỉ mục hoặc số của các thường trình trong thư viện. Phần lớn công việc liên kết được thực hiện tại thời điểm ứng dụng được tải (loadtime) hoặc trong khi thực hiện (runtime). Thông thường, chương trình liên kết cần thiết, được gọi là "trình liên kết động" hoặc "trình tải liên kết", thực sự là một phần của hệ điều hành cơ bản. (Tuy nhiên, có thể, và không quá khó, để viết một chương trình sử dụng liên kết động và bao gồm trình liên kết động của chính nó, ngay cả đối với một hệ điều hành không hỗ trợ liên kết động.)

Các lập trình viên ban đầu đã phát triển liên kết động trong hệ điều hành Multics, bắt đầu từ năm 1964 và MTS (Michigan Terminal System), được xây dựng vào cuối những năm 1960.[10]

Tối ưu hóa

Vì các thư viện dùng chung trên hầu hết các hệ thống không thay đổi thường xuyên, nên các hệ thống có thể tính toán địa chỉ tải có khả năng cho mỗi thư viện dùng chung trên hệ thống trước khi cần và lưu trữ thông tin đó trong thư viện và các file thực thi. Nếu mọi thư viện chia sẻ được tải đã trải qua quá trình này, thì mỗi thư viện sẽ tải tại địa chỉ được xác định trước, giúp tăng tốc quá trình liên kết động. Tối ưu hóa này được gọi là prebinding trong macOS và prelinking trong Linux. Nhược điểm của kỹ thuật này bao gồm thời gian cần thiết để tính toán trước các địa chỉ này mỗi khi thư viện chia sẻ thay đổi, không thể sử dụng ngẫu nhiên bố cục không gian địa chỉ và yêu cầu đủ không gian địa chỉ ảo để sử dụng (một vấn đề sẽ được giảm bớt khi áp dụng kiến trúc 64-bit, ít nhất là trong thời điểm hiện tại).

Định vị thư viện trong thời gian chạy

Các trình tải cho các thư viện chia sẻ rất đa dạng về chức năng. Một số phụ thuộc vào các đường dẫn lưu trữ rõ ràng đến các thư viện. Bất kỳ thay đổi nào đối với việc đặt tên thư viện hoặc bố cục của hệ thống file sẽ khiến các hệ thống này bị lỗi. Thông thường hơn, chỉ có tên của thư viện (chứ không phải đường dẫn) được lưu trữ trong file thực thi, với hệ điều hành cung cấp phương thức để tìm thư viện trên đĩa, dựa trên một số thuật toán.

Nếu một thư viện dùng chung mà một file thực thi phụ thuộc vào sẽ bị xóa, di chuyển hoặc đổi tên hoặc nếu một phiên bản thư viện không tương thích được sao chép vào một vị trí sớm hơn trong tìm kiếm, thì file thực thi sẽ không tải được. Đây được gọi là địa ngục phụ thuộc, tồn tại trên nhiều nền tảng. Biến thể Windows (khét tiếng) thường được gọi là địa ngục DLL. Vấn đề này không thể xảy ra nếu mỗi phiên bản của mỗi thư viện được xác định duy nhất và mỗi chương trình chỉ tham chiếu các thư viện bằng các định danh duy nhất đầy đủ của chúng. Các vấn đề "địa ngục DLL" với các phiên bản Windows trước đó phát sinh từ việc chỉ sử dụng tên của các thư viện không được bảo đảm là duy nhất để giải quyết các liên kết động trong các chương trình. (Để tránh "DLL hell", các phiên bản Windows sau này chủ yếu dựa vào các tùy chọn cho các chương trình cài đặt DLL riêng - về cơ bản là rút lui một phần khỏi việc sử dụng các thư viện dùng chung - cùng với các cơ chế để ngăn thay thế DLL hệ thống dùng chung với các phiên bản trước đó.)

Microsoft Windows

Microsoft Windows kiểm tra registry để xác định vị trí thích hợp để tải DLL thực hiện các đối tượng COM, nhưng đối với các DLL khác, nó sẽ kiểm tra các thư mục theo thứ tự xác định. Đầu tiên, Windows kiểm tra thư mục nơi nó tải chương trình (private DLL); bất kỳ thư mục nào được đặt bằng cách gọi hàm SetDllDirectory(); các thư mục System32, System và Windows; sau đó là thư mục làm việc hiện tại; và cuối cùng là các thư mục được chỉ định bởi biến môi trường PATH.[11] Ứng dụng viết cho .NET Framework (từ năm 2002), cũng kiểm tra Global hội Cache là kho lưu trữ chính của các Global Assembly Cache là kho lưu trữ chính của các file dll được chia sẻ để loại bỏ vấn đề về địa ngục DLL.

OpenStep

OpenStep đã sử dụng một hệ thống linh hoạt hơn, thu thập danh sách các thư viện từ một số vị trí đã biết (tương tự như khái niệm PATH) khi hệ thống khởi động lần đầu tiên. Di chuyển các thư viện xung quanh không gây ra vấn đề gì cả, mặc dù người dùng phải chịu chi phí thời gian khi lần đầu tiên khởi động hệ thống.

Các hệ thống tương tự Unix

Hầu hết các hệ thống tuơng tự Unix đều có "đường dẫn tìm kiếm" chỉ định các thư mục hệ thống file để tìm thư viện động. Một số hệ thống chỉ định đường dẫn mặc định trong file cấu hình, một số hệ thống khác mã hóa nó vào trình tải động. Một số định dạng file thực thi có thể chỉ định các thư mục bổ sung để tìm kiếm thư viện cho một chương trình cụ thể. Điều này thường có thể được ghi đè bằng một biến môi trường, mặc dù nó bị vô hiệu hóa cho các chương trình setuid và setgid, do đó người dùng không thể buộc chương trình đó chạy mã tùy ý với quyền gốc. Các nhà phát triển thư viện được khuyến khích đặt thư viện động của họ ở những nơi trong đường dẫn tìm kiếm mặc định. Mặt khác, điều này có thể làm cho việc cài đặt các thư viện mới gặp vấn đề và các vị trí "đã biết" này nhanh chóng trở thành nhà của số lượng file thư viện ngày càng tăng, khiến việc quản lý trở nên phức tạp hơn.

Tải động

Tảo động (Dynamic loading), một tập hợp con của liên kết động, bao gồm tải và dỡ tải thư viện được liên kết động tại thời gian chạy theo yêu cầu. Một yêu cầu như vậy có thể được thực hiện ngầm trong thời gian biên dịch hoặc rõ ràng vào thời gian chạy. Các yêu cầu ngầm được thực hiện tại thời điểm biên dịch khi một trình liên kết thêm các tham chiếu thư viện bao gồm các đường dẫn file hoặc chỉ đơn giản là tên file. Yêu cầu rõ ràng được thực hiện khi các ứng dụng thực hiện cuộc gọi trực tiếp tới API của hệ điều hành trong thời gian chạy.

Hầu hết các hệ điều hành hỗ trợ các thư viện được liên kết động cũng hỗ trợ tải động các thư viện đó thông qua API liên kết thời gian chạy. Ví dụ, Microsoft Windows sử dụng các hàm API LoadLibrary, LoadLibraryEx, FreeLibrary và GetProcAddress với Microsoft Dynamic Link Libraries; Các hệ thống dựa trên POSIX, bao gồm hầu hết các hệ thống tương tự UNIX và UNIX, sử dụng dlopen , dlclose và dlsym . Một số hệ thống phát triển tự động hóa quá trình này.